home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / pdclk145.zip / IP.ASM < prev    next >
Assembly Source File  |  1992-10-03  |  56KB  |  2,387 lines

  1. ;        ip.asm
  2. ;========================================================================
  3.  
  4. ; Copyright (C) 1991 by Jan.Engvald@ldc.lu.se, see file COPYING.
  5.  
  6. ;************************************************************************
  7. ;************************************************************************
  8. ;*
  9. ;*        UDP/IP library
  10. ;*
  11. ;* This library is in a transition phase from a PDCLKSET specific library
  12. ;* into a multiprocess, reentrant, any hardware type, general UDP/IP
  13. ;* library. The buffers used have a descriptor part and a packet part.
  14. ;* The descriptor part is used to allow reentrancy, different physical 
  15. ;* address lengths and varying number of IP options.
  16. ;*
  17. ;* In this library DS:BX always points to the descriptor buffer, DS:DI
  18. ;* usually points to the physical header/IP header/UDP header part of
  19. ;* the IP packet buffer and DX,AX often contains an IP number in network
  20. ;* byte order (DL,DH,AL,AH). For efficiency reasons, IP numbers are
  21. ;* searched last half first (first halves are often equal).
  22. ;*
  23. ;* As this library is still evolving, you can not assume that it looks
  24. ;* the same in the next release. In particular, if you are using any of
  25. ;* of the subroutines, check if their calls or results have been changed.
  26. ;*
  27. ;* The current implementation is RFC791 (IP) and RFC1122 (host requirements)
  28. ;* compliant, except for a few cases: I havn't found a reasonable solution
  29. ;* on how to report back to the application ICMP errors like parameter
  30. ;* problem, protocol and port unreachables, and fragment reassembly time
  31. ;* exceeded. Also, IP options are allowed, but the interpretation and handling
  32. ;* must be done by the application. Apart from the above, it is a de luxe
  33. ;* implementation that includes things like multiple default gateways,
  34. ;* sending protocol and port unreachables, IP type of service handling (not
  35. ;* tested), fragment reassembly and source quench introduced delay.
  36. ;*
  37. ;************************************************************************
  38. ;************************************************************************
  39.  
  40.                         ; send errors:
  41. SERRUNREACH    equ    0            ; host or net unreachable
  42. SERRNOBUF    equ    2            ; temporary out of buffers
  43. SERRNOARP    equ    4            ; got no ARP reply
  44. SERRTIMOUT    equ    6            ; general timeout
  45. SERRNOTRAF    equ    8            ; received no traffic from dst
  46. SERRNOIP    equ    10            ; no IP # to send to
  47.  
  48. ICMP_PROT    equ    1            ; Internet Control Msg Prot
  49. UDP_PROT    equ    17            ; IP protocol type UDP
  50.  
  51. Descriptor    struc
  52. dLink        LinkStruc    <>        ; next & prev links
  53. ; dIOCB        iocb    <>            ; pkt drvr hi perf struc
  54. dPtrPhys    dw    0            ; ptr to physical hdr
  55. dPtrIp        dw    0            ; ptr to IP hdr
  56. dPtrUdp     dw    0            ; ptr to UDP hdr
  57. dPktLen     dw    0            ; packet length (bytes)
  58. dPktEnd     dw    0            ; end of packet
  59. dTimOut2Msg    equ    dPktEnd            ; Timeout msg for findsends
  60. dSqDelay    dw    0            ; source quench delay (ms)
  61. dWaitEvent    dw    0            ; event to wait for
  62. dPtrFrag    equ    dWaitEvent        ; ptr to defargment listhead
  63. dTimOutMsg    dw    0            ; to be displayed at timeout
  64. dTickResend    dw    1*18            ; resend start interval (ticks)
  65. dTickTimeout    dw    4*18            ; timeout ticks (in 1/18 s)
  66. dTick2Timeout    dw    14*18            ; second timeout
  67. dIdxHwDst    equ    dSqDelay        ; arp table index for hw dst
  68. dIdxIpDst    equ    dTick2Timeout        ; arp table index for IP dst
  69. dAdjust     equ    (4-(($-dLink) and 3)) and 3
  70. if    dAdjust
  71.         db    dAdjust dup (0)
  72. endif
  73. dGwys2Chk    db    0            ; # of untried gateways
  74. dSnap        db    0            ; 802.3 snaps used
  75. dPtrDes     dw    0            ; ptr to start of descriptor
  76. dHwDst        equ    $-dLink         ; (part of pd packet)
  77. DESCRLEN    equ    $-dLink
  78. Descriptor    ends
  79.  
  80. HwStruc     struc
  81. hEthDst     db    6 dup (0)        ; Ethernet destination address
  82. hEthSrc     db    6 dup (0)        ; my Ether addr
  83. hProtType    dw    0008            ; 0800 = IP
  84. HWHDRLEN    equ    $-hEthDst
  85. HwStruc     ends
  86.  
  87. SnapStruc    struc
  88. sDSAP        db    170
  89. sSSAP        db    170
  90. sContr        db    3
  91. sOrgCode    db    0,0,0
  92. sProt        db    08, 00
  93. SNAPLEN     equ    $-sDSAP
  94. SnapStruc    ends
  95.  
  96. IpStruc     struc
  97. iIpVerHlen    db    45h            ; ver 4, 5 32-bit hdr words
  98. iIpTos        db    0            ; type of service
  99. iIpLen        dw    0            ; IP packet length
  100. iIpId        dw    0100h            ; id 0001
  101. iIpFlFrag    dw    0            ; no flags or fragments
  102. iIpTtl        db    90            ; time to live
  103. iIpProt     db    0            ; 17 = udp
  104. iIpXsum     dw    0            ; header checksum
  105. iIpSrc        dw    0, 0            ; Don't know my IP nmbr
  106. iIpDst        dw    0ffffh, 0ffffh        ; local net broadcast IP
  107. iIpOptions    equ    $-iIpVerHlen
  108. IPHDRLEN    equ    $-iIpVerHlen
  109. IpStruc     ends
  110.  
  111. UdpStruc    struc
  112. uUdpSrc     dw    4400h            ; source port 44h = 68
  113. uUdpDst     dw    4300h            ; dest port 43h = 67
  114. uUdpLen     dw    0            ; length in bytes
  115. uUdpXsum    dw    0            ; udp checksum
  116. uUdpData    equ    $-uUdpSrc
  117. UDPHDRLEN    equ    $-uUdpSrc
  118. UdpStruc    ends
  119.  
  120. BootpStruc    struc
  121. uUdpStruc    UdpStruc    <>
  122. uBotOp        db    1            ; bootp request
  123. uBotHtype    db    0            ; hardware type
  124. uBotHlen    db    0            ; hardware addr lenght
  125. uBotHops    db    0            ; hops
  126. uBotXid     dw    0, 0            ; transaction id
  127. uBotSecs    dw    0001            ; 0100h seconds since boot
  128. uBotUnused    dw    0            ; not defined
  129. uBotCliIp    dw    0, 0            ; Client IP unknown
  130. uBotYourIp    dw    0, 0            ; my IP yet unknown
  131. uBotServIp    dw    0, 0            ; Server IP
  132. uBotGwyIp    dw    0, 0            ; Gateway IP
  133. uBotCliHwAd    db    16 dup (0)        ; My Hardware address
  134. uBotSname    db    64 dup (0)        ; server name
  135. uBotFilNam    db    128 dup (0)        ; file name
  136. uBotMagNum    dw    8263h, 6353h        ; Magic number
  137. uBotVend    db    64-4 dup (0)        ; Vendor specific area
  138. BpDataLen    =    $-uBotOp
  139. BootpStruc    ends
  140.  
  141. IcmpStruc    struc
  142. uIcmpTypecode    dw    0
  143. uIcmpXsum    dw    0
  144. uIcmpData    dw    0, 0
  145. uIcmpIpHdr    dw    iIpOptions+4 dup (0)
  146. ICMPHDRLEN    equ    uIcmpIpHdr-uIcmpTypecode
  147. IcmpStruc    ends
  148.  
  149. BootpFrame    struc
  150. fDescriptor    Descriptor    <>
  151. fHwStruc    HwStruc     <>
  152. fIpStruc    IpStruc     <>
  153. fBotStruc    BootpStruc    <>
  154. BpLen        =    $-fHwStruc
  155. BootpFrame    ends
  156.  
  157.         even
  158. Events        dw    1            ; =1 so DONT_WAIT always true
  159. DONT_WAIT    equ    1
  160. GOT_BOOTP    equ    2
  161. GOT_ARPREPLY    equ    4
  162. GOT_TIMEREPLY    equ    8
  163. GOT_ARPREQ    equ    16
  164. GOT_ICMPMSG    equ    32
  165. GOT_NSREPLY    equ    64
  166.  
  167. GenFlags    dw    0
  168. ARGZONE     equ    2
  169. ARGZONESPEC    equ    4
  170. DSTNOW        equ    8
  171. IS_386        equ    16
  172. TBL_READY    equ    32
  173. UDP_ECHO    equ    64
  174. DBGINTERR    equ    08000h
  175.  
  176. MySegm        dw    0
  177. Hlen        dw    0
  178. H2Len        dw    0
  179. MyMask        dw    2 dup (0h)
  180. MyNet        dw    2 dup (0h)
  181. IpHandle    dw    0
  182. IpIdCounter    dw    0
  183. InSendAndW    dw    0
  184. LongerTimOut    dw    0
  185.  
  186. ifndef        MAXDEFGWYS
  187. MAXDEFGWYS    equ    4
  188. endif
  189.  
  190. DefGwyIndex    dw    0
  191. DefGwyNum    dw    0
  192. DefGwys     dw    MAXDEFGWYS*2 dup (0)
  193.  
  194. if TBLBUILD or PINGCLIENT
  195. DefNSnum    dw    0
  196. DefNS        dw    MAXDEFNS*2 dup (0)
  197. endif ; TBLBUILD or PINGCLIENT
  198.  
  199. ifndef        ROUTESLOTS
  200. ROUTESLOTS    equ    8
  201. endif
  202.  
  203. ; The route table contains information on hosts behind gateways.
  204. ;
  205. ; If we don't receive anything from an IP number within one minute after we
  206. ; last sent to it, we return SERRNOTRAF on the next send. This is cleared
  207. ; after another minute.
  208.  
  209. RouteTabIpD2    dw    ROUTESLOTS dup (0)    ; destination IP #
  210. RouteTabIpD1    dw    ROUTESLOTS dup (0)
  211. RouteTabTos    dw    ROUTESLOTS dup (0)    ; type of service
  212. RouteTabIpG2    dw    ROUTESLOTS dup (0)    ; gateway IP #
  213. RouteTabIpG1    dw    ROUTESLOTS dup (0)
  214. RouteTabTrTx    dw    ROUTESLOTS dup (0)    ; transmitt timer
  215. RouteTabTrRx    dw    ROUTESLOTS dup (0)    ; receive timer
  216. RouteTabFlags    dw    ROUTESLOTS dup (0)    ; flags (must follow TrRx)
  217. RouteTabTrSq    dw    ROUTESLOTS dup (0)    ; source quench timer
  218. RouteTabSqDelay dw    ROUTESLOTS dup (0)    ; source quench delay
  219. RouteTabUnreach dw    ROUTESLOTS dup (0)    ; destination unreachable
  220.  
  221. RoutePutSlot    dw    0
  222.  
  223. IpDesBuf    BootpFrame    <>
  224.  
  225. SnapHdr     SnapStruc    <>
  226.  
  227. IpHdr        equ    IpDesBuf.fIpStruc
  228. MyIpNr        equ    IpDesBuf.fIpStruc.iIpSrc
  229.  
  230.  
  231.  
  232. ;************************************************************************
  233. ;*        SendUdpFind
  234. ;*
  235. ;*    Input:        BX = IP description buffer ptr (BX saved)
  236. ;*            DX = addr of length prepended IP list to send to until reply
  237. ;*    Output:     Zero and CX = 0 if OK
  238. ;*            non-zero and CX = errorcode if error 
  239. ;*    Destroys:    AX, CX, DX, SI, DI, ES and flags
  240. ;************************************************************************
  241.  
  242. SendUdpFind    proc    near
  243.         mov    [bx].dTimoutMsg,0    ; continue even if no reply
  244.         mov    ah,2            ; do 2 turns over all IP #s
  245.   Send2ndTurn:
  246.         mov    si,dx            ; get IP list addr
  247.         lodsb                ; # of IP numbers to al
  248.         mov    cx,SERRNOIP
  249.         or    al,al
  250.         jz    SendUdpFindRet
  251.  
  252.         inc    si
  253.   SendNextIP:
  254.         mov    di,[bx].dPtrIp
  255.         lea    di,[di].iIpDst
  256.         movsw                ; put next IP number
  257.         movsw
  258.  
  259.         cmp    ax,0101h        ; last IP last turn?
  260.         jne    Send2orMore
  261.         mov    di,[bx].dTimOut2Msg
  262.         mov    [bx].dTimoutMsg,di    ; -yes, terminate if no reply
  263.   Send2orMore:
  264.         push    ax
  265.         push    dx
  266.         push    si
  267.         mov    ax,[bx].dPktLen
  268.         call    SendUdpPkt        ; send udp packet
  269.         pop    si
  270.         pop    dx
  271.         pop    ax
  272.         jz    SendUdpFindRet        ; done if reply
  273.  
  274.         dec    al
  275.         jnz    SendNextIP        ; more IP numbers this turn?
  276.  
  277.         mov    di,[bx].dTick2Timeout    ; -no, use longer timeout
  278.         mov    [bx].dTickTimeout,di    ;   for 2nd turn
  279.         dec    ah
  280.         jnz    Send2ndTurn        ; both turns done?
  281.  
  282.   SendUdpFindRet:
  283.         or    cx,cx
  284.         ret
  285. SendUdpFind    endp
  286.  
  287.  
  288.  
  289. ;************************************************************************
  290. ;*        SendUdpPkt
  291. ;*
  292. ;*    Input:        AX = IP data byte length (AX destroyed)
  293. ;*            BX = IP description buffer ptr (BX saved)
  294. ;*    Output:     Zero and CX = 0 if OK
  295. ;*            non-zero and CX = errorcode if error 
  296. ;*    Destroys:    AX, CX, DX, SI, DI, ES and flags
  297. ;************************************************************************
  298.  
  299. SendUdpPkt    proc    near
  300.         push    ax
  301.         mov    si,offset MyIpNr    ; fill in my IP # (used
  302.         mov    di,[bx].dPtrIp        ;   in udp chksum!)
  303.         add    di,iIpSrc
  304.         movsw
  305.         movsw
  306.         xchg    ah,al
  307.         mov    di,[bx].dPtrUdp
  308.         mov    [di].uUdpLen,ax     ; fill in UDP total length
  309.  
  310.         mov    [di].uUdpXsum,ax    ; ensure chksum is calculated
  311.  
  312.         mov    di,[bx].dPtrIp
  313.         mov    [di].iIpProt,UDP_PROT    ; set UDP protocol
  314.  
  315.         call    UdpChkSum        ; calculate UDP checksum
  316.  
  317.         pop    ax
  318.         call    SendIpPkt        ; send UDP packet
  319.  
  320.         ret
  321. SendUdpPkt    endp
  322.  
  323.  
  324.  
  325. ;************************************************************************
  326. ;*        SendIcmpPkt
  327. ;*
  328. ;*    Input:        BX = IP description buffer ptr (BX saved)
  329. ;*            CX = IP data length
  330. ;*    Output:     Zero and CX = 0 if OK
  331. ;*            non-zero and CX = errorcode if error 
  332. ;*    Destroys:    AX, CX, DX, SI, DI, ES and flags
  333. ;************************************************************************
  334.  
  335. SendIcmpPkt    proc    near
  336.         push    cx            ; save length
  337.  
  338.         call    IcmpChkSum        ; calculate icmp checksum
  339.  
  340.         mov    [bx].dWaitEvent,0    ; don't wait for answer
  341.         mov    di,[bx].dPtrIp
  342.         mov    [di].iIpProt,ICMP_PROT
  343.  
  344.         pop    ax            ; restore length
  345. ;        call    SendIpPkt
  346. ;        ret
  347. SendIcmpPkt    endp
  348.  
  349.  
  350.  
  351. ;************************************************************************
  352. ;*        SendIpPkt
  353. ;*
  354. ;*    Input:        AX = IP data byte length (AX destroyed)
  355. ;*            BX = IP description buffer ptr (BX saved)
  356. ;*    Output:     Zero and CX = 0 if OK
  357. ;*            non-zero and CX = errorcode if error 
  358. ;*    Destroys:    AX, CX, DX, SI, DI, ES and flags
  359. ;************************************************************************
  360.  
  361. SendIpPkt    proc    near
  362. if PINGCLIENT
  363.         mov    cx,ax
  364.         add    cx,IPHDRLEN+14+8+4+12    ; preamble, crc, intergap ...
  365.         cli
  366.         add    EchoLoad+2,cx
  367.         adc    EchoLoad,0
  368.         sti
  369. endif ; PINGCLIENT
  370.         call    IPHdrLength        ; calculate IP hdr length
  371.  
  372.         mov    dx,MyIpNr        ; my IP # to IP src
  373.         mov    [si].iIpSrc,dx
  374.         mov    dx,MyIpNr+2
  375.         mov    [si].iIpSrc+2,dx
  376.  
  377.         add    ax,cx            ; add hdr length to data length
  378.         mov    [bx].dPktLen,ax     ;   and save it
  379.  
  380.         xchg    ah,al
  381.         mov    [si].iIpLen,ax        ; fill in IP length
  382.  
  383.         mov    dx,IpIdCounter
  384.         mov    [si].iIpId,dx        ; unique id for frag reassembly
  385.         inc    dx
  386.         mov    IpIdCounter,dx
  387.  
  388.         call    IpChkSum        ; calculate checksum
  389. if RFCC
  390.         call    Ageing            ; clear unused table slots
  391. endif ; RFCC
  392.         call    PutPhysDst        ; do we have HW dest addr?
  393.         jnz    SendIpRet        ; -no, ARP timed out
  394.  
  395.         call    PutPhysSrc        ; put my HW src addr
  396.  
  397.         add    [bx].dPktLen,cx     ; pkt length (HW addr part)
  398.  
  399.         jmp    short SendAndWait    ; -yes, send packet
  400.   SendIpRet:
  401.         ret
  402. SendIpPkt    endp
  403.  
  404.  
  405.  
  406. ;************************************************************************
  407. ;*        SendAndWait
  408. ;*    Input:        BX = description buffer ptr (saved)
  409. ;*    Output:     Zero and CX = 0 if OK
  410. ;*            non-zero and CX = errorcode if error 
  411. ;*    Destroys:    AX, CX, DX, SI, DI, ES, flags
  412. ;************************************************************************
  413.  
  414. SendAndWait    proc    near
  415.         inc    InSendAndW
  416.         mov    si,[bx].dWaitEvent    ; event to wait for
  417.  
  418.         or    si,si            ; no event to wait for?
  419.         jz    SendDontWait
  420.  
  421.         not    si
  422.         and    Events,si        ; clear this event bit
  423.   SendDontWait:
  424.         not    si
  425. if RFCC
  426. ; Do RFC1016 Source Quench Introduced Delay
  427.  
  428.         mov    ax,[bx].dSqDelay    ; SQ delay (ms)
  429.         add    ax,32            ; round up
  430.         mov    cl,6
  431.         shr    ax,cl            ; convert ms to ticks
  432.         call    CurrentTicks
  433.         add    ax,cx            ; time to send at
  434.   SendSqLoop:
  435.         call    CurrentTicks
  436.         cmp    cx,ax            ; can we send it now?
  437.         jns    SendNoSqDelay
  438.         call    Something2Do        ; - no, wait a while
  439.         jmp    short SendSqLoop
  440.   SendNoSqDelay:
  441. else
  442.         call    CurrentTicks
  443. endif ; RFCC
  444.         call    SendRawPkt        ; send packet part of buffer
  445.  
  446.         mov    di,[bx].dTickResend    ; first resend time
  447.         mov    ax,cx
  448.         add    ax,di
  449.         add    ax,LongerTimOut
  450.  
  451.         mov    dx,cx
  452.         add    dx,LongerTimOut
  453.         add    dx,[bx].dTickTimeout    ; time out time
  454.   WaitLoop:
  455.         test    Events,si        ; got what we want?
  456.         jz    SendChk
  457.   SendWaitOK:
  458.         xor    cx,cx
  459.   SendWaitRet:
  460.         dec    InSendAndW
  461.         or    cx,cx
  462.         ret
  463.  
  464.   SendChk:
  465.         call    Something2Do        ; anything else to do?
  466.   ChkTimeout:
  467.         call    CurrentTicks
  468.         cmp    cx,dx            ; time out?
  469.         jns    SendTimedout
  470.  
  471.         cmp    cx,ax            ; time to resend?
  472.         js    WaitLoop
  473.  
  474.         shl    di,1            ; double resend time    
  475.  
  476.         cmp    di,30*18
  477.         jbe    SendDouble
  478.         mov    di,30*18        ; max 30 seconds
  479.   SendDouble:
  480.         add    ax,di            ; next resend time
  481.  
  482.         call    SendRawPkt        ; send same packet again
  483.         jmp    short WaitLoop
  484.   SendTimedout:
  485.         mov    dx,[bx].dTimOutMsg
  486.         mov    cx,SERRTIMOUT
  487.         or    dx,dx            ; if no timeout msg
  488.         jz    SendWaitRet        ;   just return
  489.  
  490.         mov    ah,9            ; print error msg in dx
  491.         int    21h
  492.         mov    al,04            ; error code 4
  493.         call    Terminate
  494. SendAndWait    endp
  495.  
  496.  
  497.  
  498. ;************************************************************************
  499. ;*        SendRawPkt
  500. ;*    Input:        BX = description buffer ptr (saved)
  501. ;*    Destroys:    flags
  502. ;*
  503. ;* (The saving of all registers below is not needed for the Crynwr
  504. ;* collection of packet drivers, but as far as I understand the packet
  505. ;* driver specification other drivers may need it.)
  506. ;************************************************************************
  507.  
  508. SendRawPkt    proc    near
  509.         push    dx
  510.         push    ax
  511.         mov    ax,3000
  512.   SendRawAgain:
  513.         push    cx
  514.         push    bx
  515.         push    ax
  516.         push    si
  517.         push    di
  518.         push    bp
  519.         push    es
  520.  
  521.         mov    si,[bx].dPtrPhys    ; get start of packet
  522.         mov    cx,[bx].dPktLen     ; and its length
  523.  
  524.         mov    ah,4            ; send packet to
  525.         push    ds            ;   packet driver
  526.         int_pkt
  527.         pop    ds
  528.  
  529.         pop    es
  530.         pop    bp
  531.         pop    di
  532.         pop    si
  533.         pop    ax
  534.         pop    bx
  535.         pop    cx
  536.  
  537.         jc    SendBadPkt        ; any errors?
  538.  
  539.         pop    ax
  540.         pop    dx
  541.         ret
  542.  
  543.   SendBadPkt:
  544.         cmp    dh,CANT_SEND        ; can't send?
  545.         jne    SendPermBad
  546.   SendTempBad:                
  547.         dec    ax            ; have we tried enough times?
  548.         jnz    SendRawAgain
  549.   SendPermBad:
  550.         stc
  551.         call    print_error        ; display explanation
  552.  
  553.         mov    al,03            ; error code 3
  554.         call    Terminate
  555. SendRawPkt    endp
  556.  
  557.  
  558.  
  559. ;************************************************************************
  560. ;*        PutPhysSrc
  561. ;*
  562. ;*    Input:        BX = IP description buffer ptr (saved)
  563. ;*    Output:     HW src addr and IP prot type put into pkt
  564. ;*            CX = phys header length
  565. ;*    Destroys:    CX, SI, DI, ES, flags
  566. ;************************************************************************
  567.  
  568. PutPhysSrc    proc    near
  569.         mov    si,offset MyHwAd    ; get my HW addr from ARP buf
  570.         mov    di,[bx].dPtrPhys
  571.         mov    cx,Hlen
  572.         add    di,cx
  573.         push    cs
  574.         pop    es
  575.         rep    movsb            ; put my HW addr as src HW addr
  576.  
  577.         test    [bx].dSnap,1
  578.         jz    PutPhysNotSnap
  579.  
  580.         mov    cx,[bx].dPktLen
  581.         add    cx,8
  582.         xchg    ch,cl
  583.         mov    [di],cx
  584.         add    di,2
  585.  
  586.         mov    cx,sProt-sDSAP
  587.         mov    si,offset SnapHdr
  588.         rep    movsb
  589.   PutPhysNotSnap:
  590.         mov    cx,di
  591.         sub    cx,[bx].dPtrPhys
  592.         add    cx,2            ; physical header length
  593.  
  594.         mov    word ptr [di],0008h    ; protocol type IP (0800)
  595.  
  596.         ret
  597. PutPhysSrc    endp
  598.  
  599.  
  600.  
  601. ;************************************************************************
  602. ;*        PutPhysDst
  603. ;*
  604. ;*    Input:        BX = IP description buffer ptr (saved)
  605. ;*    Output:     Zero and CX = 0 if OK
  606. ;*            non-zero and CX = errorcode if error 
  607. ;*    Destroys:    AX, CX, DX, SI, DI, ES, flags
  608. ;************************************************************************
  609.  
  610. PutPhysDst    proc    near
  611.         mov    ax,DefGwyNum        ; # of default gwys we have
  612.         mov    [bx].dGwys2Chk,al    ; gwys still left to check
  613.   PutPhysAgain:
  614.         mov    di,[bx].dPtrIp
  615.         mov    al,[di].iIpTos        ; get type of service
  616.         xor    ah,ah
  617.         mov    si,ax
  618.  
  619.         mov    dx,[di].iIpDst        ; set dx,ax = dst IP #
  620.         mov    ax,[di].iIpDst+2
  621.  
  622.         call    ArpPutHwDst        ; do we know dst phys addr?
  623.         jz    FoundArpEntry        ; - yes, copied hw addr
  624.  
  625.         call    MyNetChk        ; - no. Is dst on my net?
  626.         jz    PutMynetArp        ;   - yes, don't use gwy
  627.                         ;       and ARP dst
  628.         call    UseGwy            ;   - no, use a gateway
  629.         jcxz    PutArp            ; destination unreachable?
  630.         jmp    short PutPhysRet
  631.  
  632.   PutMynetArp:
  633.         mov    [bx].dGwys2Chk,1
  634.   PutArp:
  635.         call    ArpPutHwDst        ; have hw addr for this IP # ?
  636.         jz    FoundArpEntry        ; - yes, copied hw addr to pkt
  637.  
  638.         call    SendArpReq        ; - no, arp for it
  639.         jz    PutPhysAgain        ; if reply, put in hw addr
  640.  
  641.         call    SwitchGwy        ;   else try next gwy
  642.  
  643.         mov    cx,SERRNOARP
  644.         dec    [bx].dGwys2Chk        ; any more default gwys?
  645.         jnz    PutPhysAgain
  646.  
  647.   PutPhysRet:
  648.         or    cx,cx
  649.   FoundArpEntry:
  650.         ret
  651. PutPhysDst    endp
  652.  
  653.  
  654.  
  655. ;************************************************************************
  656. ;*        RouteFind
  657. ;*
  658. ;*    Input:        DX = first word of dst IP # (saved if not found)
  659. ;*            AX = second word of dst IP # (saved if not found)
  660. ;*            SI = IP type of service
  661. ;*    Output:     if found: zero and DI = route table index
  662. ;*                  DX = first word of gwy IP #
  663. ;*                  AX = second word of gwy IP #
  664. ;*                  CX = net/host unreachable code
  665. ;*    Destroys:    CX, DI, ES, flags
  666. ;************************************************************************
  667.  
  668. RouteFind    proc    near
  669.         mov    di,offset RouteTabIpD2
  670.         mov    cx,ROUTESLOTS
  671.         or    cx,cx            ; ensure non-zero flag
  672.         PushfDI
  673.   RouteFindNext:                ; look for matching slot
  674.         repne    scasw
  675.         jnz    RouteFindRet
  676.  
  677.         cmp    dx,2*RouteSLOTS-2[di]    ; does dst IP first part match?
  678.         jne    RouteFindNext        ; - no, look further
  679.  
  680.         cmp    si,4*RouteSLOTS-2[di]    ; does dst tos    match?
  681.         jne    RouteFindNext        ; - no, look further
  682.  
  683.         sub    di,offset RouteTabIpD2+2 ;- yes, compute slot index
  684.  
  685.         mov    dx,RouteTabIpG1[di]    ; get gwy IP #
  686.         mov    ax,RouteTabIpG2[di]    ;
  687.  
  688.         mov    cx,RouteTabUnreach[di]    ; get unreachable code
  689.  
  690.         PopfEI
  691.         cmp    di,di            ; set zero flag
  692.         ret                ; zero (found) return
  693.  
  694.   RouteFindRet:
  695.         PopfEI
  696.         ret                ; non zero (not found) return
  697. RouteFind    endp
  698.  
  699.  
  700.  
  701. ;************************************************************************
  702. ;*        MyNetChk
  703. ;*
  704. ;*    Input:        DX = first word of IP # (saved)
  705. ;*            AX = second word of IP # (saved)
  706. ;*    Output:     zero if same net else non-zero 
  707. ;*    Destroys:    flags
  708. ;************************************************************************
  709.  
  710. MyNetChk    proc    near
  711.         push    ax
  712.         push    dx
  713.  
  714.         and    dx,MyMask        ; check if my net
  715.         cmp    dx,MyNet
  716.         jne    MyNetRet
  717.         and    ax,MyMask+2
  718.         cmp    ax,MyNet+2
  719.   MyNetRet:
  720.         pop    dx
  721.         pop    ax
  722.         ret
  723. MyNetChk    endp
  724.  
  725.  
  726.  
  727. ;************************************************************************
  728. ;*        UseGwy
  729. ;*
  730. ;*    Input:        DX = first word of destination IP #
  731. ;*            AX = second word of destination IP #
  732. ;*            SI = IP type of service
  733. ;*    Output:     DX = first word of gateway IP #
  734. ;*            AX = second part of gateway IP #
  735. ;*            CX = net/host unreachable code
  736. ;*    Destroys:    CX, SI, DI, ES, flags
  737. ;************************************************************************
  738.  
  739. UseGwy        proc    near
  740.         PushfDI
  741.  
  742.         call    RouteFind        ; is dst in route tbl?
  743.         jz    UseGwyKnown        ; - yes, have gwy IP #
  744.                         ; - no, use default gwy
  745.         dec    cx
  746.         cmp    dl,127            ; don't send to 127.x.x.x
  747.         je    UseGwyRet
  748.  
  749.         mov    di,RoutePutSlot
  750.         add    di,2            ; advance index two bytes
  751.         cmp    di,ROUTESLOTS*2     ; at end of table?
  752.         jb    UseRouteSlot
  753.  
  754.         xor    di,di            ; - yes, wrap around
  755.   UseRouteSlot:
  756.         mov    RoutePutSlot,di
  757.         mov    RouteTabIpD1[di],dx    ; put destination IP #
  758.         mov    RouteTabIpD2[di],ax
  759.         mov    RouteTabTos[di],si
  760.  
  761.         mov    si,DefGwyIndex
  762.         shl    si,1
  763.         shl    si,1
  764.         mov    dx,DefGwys[si]
  765.         mov    ax,DefGwys+2[si]
  766.         mov    RouteTabIpG1[di],dx    ;   and default gwy IP #
  767.         mov    RouteTabIpG2[di],ax    ;   into route table
  768.  
  769.         call    CurrentTicks
  770.         mov    RouteTabTrRx[di],cx    ; put current time
  771.  
  772.         xor    cx,cx            ; initialize other fields
  773.         mov    RouteTabUnreach[di],cx    ;   clear unreachable
  774.         mov    RouteTabFlags[di],cx
  775.         mov    RouteTabSqDelay[di],cx
  776.  
  777.         or    si,dx
  778.         or    si,ax            ; any non-zero gwy IP #?
  779.         jz    UseGwyNone        ; - yes
  780.   UseGwyKnown:
  781. if RFCC
  782.         push    cx
  783.         push    ax
  784.         call    CurrentTicks
  785.         mov    RouteTabTrTx[di],cx    ; transmit time
  786.  
  787.         mov    ax,RouteTabSqDelay[di]    ; move sq delay to descriptor
  788.         mov    [bx].dSqDelay,ax
  789.         dec    ax            ; any delay?
  790.         js    UseNoSqDelay
  791.         mov    ax,RouteTabTrSq[di]    ; - yes
  792.         add    ax,18            ; has one second passed
  793.         cmp    ax,cx            ;   since we last decremented
  794.         jns    UseNoSqDelay        ;   the delay value?
  795.         mov    RouteTabTrSq[di],cx
  796.         dec    RouteTabSqDelay[di]    ; - yes, one millisecond off
  797.   UseNoSqDelay:
  798.         pop    ax
  799.         pop    cx
  800. endif ; RFCC
  801.   UsegwyRet:
  802.         PopfEI
  803.         ret
  804.  
  805.   UseGwyNone:
  806.         PopfEI
  807.         mov    dx,offset NoGwyMsg
  808.         mov    ah,9            ; - no, print error msg in dx
  809.         int    21h
  810.         mov    al,08            ; error code 8
  811.         call    Terminate
  812. UseGwy        endp
  813.  
  814.  
  815.  
  816. ;************************************************************************
  817. ;*        SwitchGwy
  818. ;*
  819. ;*    Input:        DX = first word of gateway IP # (saved)
  820. ;*            AX = second word of gateway IP # (saved)
  821. ;*    Destroys:    CX, DI, ES, flags
  822. ;************************************************************************
  823.  
  824. SwitchGwy    proc    near
  825.         PushfDI
  826.         mov    di,DefGwyIndex        ; if current default gateway
  827.         shl    di,1
  828.         shl    di,1
  829.  
  830.         cmp    dx,DefGwys[di]        ;   is the one
  831.         jne    SwitchNotThis
  832.         cmp    ax,DefGwys+2[di]    ;   that failed
  833.         jne    SwitchNotThis
  834.  
  835.         shr    di,1
  836.         shr    di,1
  837.         inc    di            ;   then switch to
  838.         cmp    di,DefGwyNum
  839.         jb    SwitchNextGwy
  840.         xor    di,di
  841.   SwitchNextGwy:
  842.         mov    DefGwyIndex,di        ;   next default gateway
  843.   SwitchNotThis:
  844.         PopfEI
  845.  
  846.         mov    di,offset RouteTabIpG2    ; remove failing gateway
  847.         mov    cx,ROUTESLOTS        ;   from all route slots
  848.         PushfDI
  849.   SwitchRouteNext:                ; look for matching slot
  850.         repne    scasw
  851.         jnz    SwitchGwyRet        ; all entries searched
  852.  
  853.         cmp    dx,2*ROUTESLOTS-2[di]    ; does gwy IP 2nd part match?
  854.         jne    SwitchRouteNext     ; - no, look further
  855.  
  856.         sub    di,offset RouteTabIpG2+2 ;- yes, clear this route
  857.         mov    RouteTabIpD1[di],0
  858.         mov    RouteTabIpD2[di],0
  859.         mov    RouteTabIpG1[di],0
  860.         mov    RouteTabIpG2[di],0
  861.         add    di,offset RouteTabIpG2+2
  862.         jmp    short SwitchRouteNext    ; more routes using this gwy?
  863.  
  864.   SwitchGwyRet:
  865.         PopfEI
  866.         ret
  867. SwitchGwy    endp
  868.  
  869.  
  870.  
  871. ;************************************************************************
  872. ;*        ChkSum
  873. ;*    Input:        SI = start addr
  874. ;*            CX = # of bytes
  875. ;*    Output:     AX = 1-complement checksum
  876. ;*            CX = partial checksum
  877. ;*            SI = addr of next byte
  878. ;*    Destroys:    Flags
  879. ;************************************************************************
  880.  
  881. ChkSum        proc    near
  882. if PINGCLIENT
  883.         test    GenFlags,IS_386
  884.         jz    ChkSum8086
  885.  
  886.         .386
  887.         push    edx            ; save 386 registers
  888.         push    eax
  889.         shr    cx,1            ; divide by two, round down
  890.         pushf                ; keep odd bit in carry
  891.         shr    cx,1
  892.         pushf
  893.         xor    edx,edx            ; clear edx and carry
  894.   ChkLoop386:
  895.         lodsd
  896.         adc    edx,eax            ; add to previous running sum
  897.         loopw    ChkLoop386
  898.  
  899.         adc    edx,0            ; add the last carry in again
  900.         mov    eax,edx
  901.         shr    eax,16
  902.         add    dx,ax
  903.         adc    dx,0
  904.  
  905.         popf                ; odd # of words?
  906.         jnc    NotOddWords
  907.  
  908.         lodsw
  909.         add    dx,ax
  910.         adc    dx,0
  911.   NotOddWords:
  912.         popf                ; odd # of bytes?
  913.         jnc    NotOddBytes
  914.  
  915.         lodsb                ; get that last byte
  916.         xor    ah,ah            ; clear carry and the high portion
  917.         add    dx,ax            ; add the last one in
  918.         adc    dx,0            ; add the carry in, too
  919.   NotOddBytes:
  920.         pop    eax
  921.         mov    ax,dx
  922.         mov    cx,dx
  923.         pop    edx
  924.  
  925.         not    ax            ; take one more 1-complement
  926.         ret
  927.  
  928.         .8086
  929. endif ; PINGCLIENT
  930.  
  931.   ChkSum8086:
  932.         push    dx
  933.         shr    cx,1            ; divide by two, round down
  934.         pushf                ; keep odd bit in carry
  935.         xor    dx,dx            ; clear dx and carry
  936.   ChkLoop:
  937.         lodsw
  938.         adc    dx,ax            ; add to previous running sum
  939.         loop    ChkLoop
  940.  
  941.         adc    dx,0            ; add the last carry in again
  942.  
  943.         popf                ; odd # of bytes?
  944.         jnc    NotOdd
  945.  
  946.         lodsb                ; get that last byte
  947.         xor    ah,ah            ; clear carry and the high portion
  948.         add    dx,ax            ; add the last one in
  949.         adc    dx,0            ; add the carry in, too
  950.   NotOdd:
  951.         mov    ax,dx
  952.         mov    cx,dx
  953.         pop    dx
  954.  
  955.         not    ax            ; take one more 1-complement
  956.         ret
  957. ChkSum        endp
  958.  
  959.  
  960.  
  961. ;************************************************************************
  962. ;*        UdpChkSum (both for generate and check!)
  963. ;*
  964. ;*    Input:        BX = IP description buffer ptr (saved)
  965. ;*    Output:     Zero if OK; checksum filled in
  966. ;*            SI = addr of next byte
  967. ;*            DI = IP Ptr
  968. ;*    Destroys:    AX, CX, DX, SI, DI, flags
  969. ;************************************************************************
  970.  
  971. UdpChkSum    proc    near
  972.         mov    si,[bx].dPtrIp
  973.         mov    di,[bx].dPtrUdp
  974.  
  975.         push    word ptr [si].iIpTtl    ; save ttl for pseudo hdr
  976.         mov    [si].iIpTtl,0        ;   usage
  977.  
  978.         xor    dx,dx
  979.         xchg    dx,[di].uUdpXsum    ; save and clear checksum
  980.  
  981.         mov    cx,[di].uUdpLen     ; save UDP length
  982.         mov    [si].iIpXsum,cx
  983.         xchg    ch,cl
  984.  
  985.         mov    ax,di
  986.         add    ax,cx
  987.         or    dx,dx            ; is there a checksum?
  988.         mov    si,ax            ; - no, not available/wanted
  989.         jz    UdpNoSum        ;   but set si to end of data
  990.  
  991.         push    cx            ; - yes
  992.         mov    cx,12            ; checksum pseudo hdr
  993.         mov    si,[bx].dPtrIp
  994.         add    si,iIpTtl
  995.         call    ChkSum
  996.  
  997.         mov    [di].uUdpXsum,cx    ; move partial checksum
  998.                         ;   into udp hdr
  999.         pop    cx            ; checksum udp hdr+data
  1000.         mov    si,di
  1001.         call    ChkSum
  1002.         jnz    UdpNotZero        ; checksum is zero?
  1003.         not    ax            ; - yes, make it FFFFh
  1004.   UdpNotZero:
  1005.         mov    [di].uUdpXsum,ax
  1006.  
  1007.         cmp    ax,dx            ; does checksums match?
  1008.   UdpNoSum:
  1009.         mov    di,[bx].dPtrIp
  1010.         pop    word ptr [di].iIpTtl    ; restore ttl
  1011.  
  1012.         ret
  1013. UdpChkSum    endp
  1014.  
  1015.  
  1016.  
  1017. ;************************************************************************
  1018. ;*        IpHdrLength
  1019. ;*
  1020. ;*    Input:        BX = IP description buffer ptr (saved)
  1021. ;*    Output:     CX = IP header byte length
  1022. ;*            SI = pointer to IP header
  1023. ;*    Destroys:    SI, flags
  1024. ;************************************************************************
  1025.  
  1026. IpHdrLength    proc    near
  1027.         mov    si,[bx].dPtrIp
  1028.         mov    cx,[si]         ; get version+length byte
  1029.         and    cx,0fh            ; length (32 bit words)
  1030.         shl    cx,1            ; convert to
  1031.         shl    cx,1            ;   byte length
  1032.         ret
  1033. IpHdrLength    endp
  1034.  
  1035.  
  1036.  
  1037. ;************************************************************************
  1038. ;*        IpChkSum (both for generate and check!)
  1039. ;*
  1040. ;*    Input:        BX = IP description buffer ptr (saved)
  1041. ;*    Output:     Zero if OK; checksum filled in
  1042. ;*    Destroys:    AX, CX, DX, SI, DI, flags
  1043. ;************************************************************************
  1044.  
  1045. IpChkSum    proc    near
  1046.         xor    dx,dx
  1047.         mov    di,[bx].dPtrIp
  1048.         xchg    dx,[di].iIpXsum     ; save and clear checksum
  1049.  
  1050.         call    IpHdrLength
  1051.         call    ChkSum            ; calculate new checksum
  1052.         mov    [di].iIpXsum,ax
  1053.  
  1054.         cmp    ax,dx            ; does checksums match?
  1055.         ret
  1056. IpChkSum    endp
  1057.  
  1058.  
  1059.  
  1060. ;************************************************************************
  1061. ;*        IcmpChkSum (both for generate and check!)
  1062. ;*
  1063. ;*    Input:        BX = IP description buffer ptr (saved)
  1064. ;*            CX = IP data length
  1065. ;*    Output:     Zero if OK; checksum filled in
  1066. ;*    Destroys:    AX, CX, DX, SI, DI, flags
  1067. ;************************************************************************
  1068.  
  1069. IcmpChkSum    proc    near
  1070.         xor    dx,dx
  1071.         mov    di,[bx].dPtrUdp
  1072.         xchg    dx,[di].uIcmpXsum    ; save and clear checksum
  1073.  
  1074.         mov    si,di
  1075.         call    ChkSum            ; calculate new checksum
  1076.         mov    [di].uIcmpXsum,ax
  1077.  
  1078.         cmp    ax,dx            ; does checksums match?
  1079.         ret
  1080. IcmpChkSum    endp
  1081.  
  1082.  
  1083.  
  1084. ;************************************************************************
  1085. ;*        CurrentTicks
  1086. ;*    Output:     CX = low word of ticks (1/18 second) counter
  1087. ;*    Destroys:    CX, ES
  1088. ;************************************************************************
  1089.  
  1090. CurrentTicks    proc    near
  1091.         mov    cx,040h         ; DOS data segment
  1092.         mov    es,cx
  1093.         mov    cx,es:6ch        ; get low word of ticks cntr
  1094.         push    cs
  1095.         pop    es
  1096.         ret
  1097. CurrentTicks    endp
  1098.  
  1099.  
  1100. if RFCC
  1101. ;************************************************************************
  1102. ;*        Ageing of ARP and Route tables
  1103. ;*
  1104. ;*    Destroys:    AX, CX, DX, SI, DI, ES, flags
  1105. ;************************************************************************
  1106.  
  1107. AgeNext     dw    0            ; time to check slots
  1108.  
  1109. Ageing        proc    near
  1110.         PushfDI
  1111.         call    CurrentTicks        ; get current ticks value
  1112.         cmp    cx,AgeNext
  1113.         jns    AgeNow            ; time to do ageing?
  1114.  
  1115.         PopfEI
  1116.         ret
  1117.  
  1118.   AgeNow:
  1119.         mov    di,cx
  1120.         mov    dx,cx
  1121.         add    cx,2*18         ; chk next 2 seconds from now
  1122.         mov    AgeNext,cx
  1123.  
  1124.         sub    dx,65*18        ; clear what is older than 1 min
  1125.  
  1126.         mov    cx,ARPSLOTS-3
  1127.         mov    si,offset ArpTabTr+6
  1128.   AgeArpLoop:
  1129.         and    word ptr [si+2*ARPSLOTS],not SQ_UPDATED ; clr every 2 s
  1130.  
  1131.         lodsw
  1132.         cmp    ax,dx
  1133.         jns    AgeArpYoung        ; not touched in a minute?
  1134.  
  1135.         sub    si,offset ArpTabTr+2
  1136.         push    cx
  1137.         push    di
  1138.         push    dx
  1139.         mov    dx,ArpTabIp1[si]
  1140.         mov    ax,ArpTabIp2[si]
  1141.         call    SwitchGwy        ; in case it's a gwy: switch
  1142.         pop    dx
  1143.         pop    di
  1144.         pop    cx
  1145.  
  1146.         xor    ax,ax
  1147.         mov    ArpTabTr[si],di     ; set current time
  1148.         mov    ArpTabIp1[si],ax    ; clear old entries
  1149.         mov    ArpTabIp2[si],ax
  1150.         mov    ArpTabHw1[si],ax
  1151.         mov    ArpTabHw2[si],ax
  1152.         mov    ArpTabHw3[si],ax
  1153.         add    si,offset ArpTabTr+2
  1154.   AgeArpYoung:
  1155.         loop    AgeArpLoop
  1156.         PopfEI
  1157.  
  1158.         mov    cx,ROUTESLOTS
  1159.         mov    si,offset RouteTabTrRx
  1160.         PushfDI
  1161.   AgeRouteLoop:
  1162.         and    word ptr [si+2*ROUTESLOTS],not SQ_UPDATED ; clr every 2 s
  1163.  
  1164.         lodsw
  1165.         cmp    ax,dx            ; old slot?
  1166.         jns    AgeRouteYoung
  1167.  
  1168.         sub    si,offset RouteTabTrRx+2
  1169.         mov    RouteTabTrRx[si],di
  1170.         xor    ax,ax
  1171.         cmp    RouteTabUnreach[si],ax    ; any error code?
  1172.         jne    AgeRouteUnr
  1173.  
  1174.         cmp    dx,RouteTabTrTx[si]    ; - no. Sent anything lately?
  1175.         jns    AgeRouteEnd        ;    - no, that's why
  1176.  
  1177.         mov    RouteTabUnreach[si],SERRNOTRAF ;- yes, somebody is dead
  1178.         jmp    short AgeRouteEnd
  1179.   AgeRouteUnr:                    ; - yes, remove slot
  1180.         mov    RouteTabIpD1[si],ax
  1181.         mov    RouteTabIpD2[si],ax
  1182.         mov    RouteTabIpG1[si],ax
  1183.         mov    RouteTabIpG2[si],ax
  1184.   AgeRouteEnd:
  1185.         add    si,offset RouteTabTrRx+2
  1186.   AgeRouteYoung:
  1187.         loop    AgeRouteLoop
  1188.  
  1189.         PopfEI
  1190.         call    AgeFrags        ; release old fragments
  1191.  
  1192.         ret
  1193. Ageing        endp
  1194.  
  1195.  
  1196.  
  1197. ;************************************************************************
  1198. ;*        VerifyIpHdr (RFC1122 requirements)
  1199. ;*
  1200. ;* verify IP dst = me (or bcast), process IP options, verify IPver=4,
  1201. ;* verify IP src not bcast, set timer value in ArpTab and RouteTab.
  1202. ;* Process IP fragments.
  1203. ;************************************************************************
  1204.  
  1205. holeStruc    struc
  1206. holeNext    dw    0
  1207. holeFirst    dw    0
  1208. holeLast    dw    0
  1209. HOLEDESCRLEN    equ    $-holeNext
  1210. holeStruc    ends
  1211.  
  1212. k18        db    18
  1213.  
  1214. VerifyIpHdr    proc    near
  1215.         push    si
  1216.         push    di
  1217.         mov    al,[di].iIpVerHlen
  1218.         and    al,0f0h
  1219.         cmp    al,040h         ; IP version 4?
  1220.         jne    VerifyErr1
  1221.  
  1222.         mov    di,[bx].dPtrPhys
  1223.         mov    si,[di]
  1224.         mov    dx,[di+2]
  1225.         mov    ax,[di+4]
  1226.         call    ArpFindHw        ; find Hw Dst arp index
  1227.         mov    [bx].dIdxHwDst,di    ;   0 = bcast, 4 = me
  1228.  
  1229.         cmp    MyIpNr,0
  1230.         je    VerifyMeNotInArp
  1231.  
  1232.         cmp    di,ARPMYIDX        ; is Hw addr to me or bcast?
  1233.         ja    VerifyErr1
  1234.   VerifyMeNotInArp:
  1235.         mov    di,[bx].dPtrPhys
  1236.         add    di,Hlen         ; get physical src addr
  1237.         mov    si,[di]
  1238.         mov    dx,[di+2]
  1239.         mov    ax,[di+4]
  1240.         call    ArpFindHw        ; is Hw Src in arp table?
  1241.         jz    VerifyChkBcast        ; - yes
  1242.  
  1243.         cmp    [bx].dIdxHwDst,ARPMYIDX ; - no. Addressed to me?
  1244.         jne    VerifyIpDst        ; 
  1245.  
  1246.         pop    di            ; - yes
  1247.         push    di
  1248.         mov    dx,[di].iIpSrc
  1249.         mov    ax,[di].iIpSrc+2
  1250.  
  1251.         call    MyNetChk        ; if he is on my net
  1252.         jnz    VerifyIpDst
  1253.  
  1254.         mov    si,[bx].dPtrPhys
  1255.         add    si,Hlen
  1256.         call    ArpPutNew        ;   add him to arp table
  1257.         jmp    short VerifyIpDst
  1258.  
  1259.   VerifyErr1:    jmp    short VerifyErr
  1260.  
  1261.   VerifyChkBcast:
  1262.         cmp    di,ARPMYIDX        ; from me or broadcast?
  1263.         jbe    VerifyErr        ; - yes, ignore packet
  1264.  
  1265.         call    CurrentTicks        ; get current ticks value
  1266.         mov    ArpTabTr[di],cx
  1267.   VerifyIpDst:
  1268.         cmp    MyIpNr,0
  1269.         je    VerifyIpUnknown
  1270.  
  1271.         pop    di
  1272.         push    di
  1273.         mov    dx,[di].iIpDst        ; check IP dst
  1274.         mov    ax,[di].iIpDst+2
  1275.         call    ArpFindIp
  1276.         mov    [bx].dIdxIpDst,di
  1277.         cmp    di,ARPMYIDX        ; is it to me or broadcast?
  1278.         ja    VerifyErr        ; - no, ignore packet
  1279.   VerifyIpUnknown:
  1280.         pop    di
  1281.         push    di
  1282.         mov    dx,[di].iIpSrc
  1283.         mov    ax,[di].iIpSrc+2
  1284.         call    ArpFindIp
  1285.         jnz    VerifyNoArp
  1286.  
  1287.         cmp    di,ARPMYIDX        ; from IP broadcast?
  1288.         jb    VerifyErr        ; -yes, ignore packet
  1289.   VerifyOK:
  1290.         call    AgeFrags        ; release old reassembly bufs
  1291.  
  1292.         pop    di
  1293.         push    di
  1294.         test    [di].iIpFlFrag,0ff3fh    ; is this a fragment?
  1295.         jnz    VerifyFrag
  1296.         clc                 ; - no, use as is
  1297.   VerifyRet:
  1298.         pop    di
  1299.         pop    si
  1300.         ret
  1301.  
  1302.   VerifyNoArp:
  1303.         pop    di
  1304.         push    di
  1305.         mov    cl,[di].iIpTos
  1306.         xor    ch,ch
  1307.         mov    si,cx
  1308.         call    RouteFind        ; is he in route table?
  1309.         jnz    VerifyNoRoute
  1310.  
  1311.         call    CurrentTicks
  1312.         mov    RouteTabTrRx[di],cx    ; note we've got pkts from him
  1313.   VerifyNoRoute:
  1314.         jmp    short VerifyOK
  1315.  
  1316.   FragAddAndErr:
  1317.         mov    si,offset FragList
  1318.         call    AddToList
  1319.   VerifyFragErr:
  1320.         mov    bx,bp
  1321.   VerifyErr:
  1322.         call    BufRelease
  1323.   VerifyKeep:
  1324.         stc
  1325.         jmp    short VerifyRet
  1326.  
  1327.   VerifyFrag:        ; RFC 815 fragment reassembly:
  1328.         mov    bp,bx            ; addr of fragment buffer
  1329.         mov    dx,[di].iIpSrc        ; get IP # / IP id / IP prot
  1330.         mov    ax,[di].iIpSrc+2
  1331.         mov    si,[di].iIpId
  1332.         mov    cx,Fraglist.lBufsAvail
  1333.         mov    ch,[di].iIpProt
  1334.   FragLook4Buf:
  1335.         mov    di,offset FragList
  1336.         call    GetFromList
  1337.         jz    FragEarliest        ; any reassembly buffers?
  1338.  
  1339.         mov    di,[bx].dPtrIp        ; match IP#/Id/Prot
  1340.         cmp    dx,[di].iIpSrc
  1341.         jne    FragNextBuf
  1342.         cmp    ax,[di].iIpSrc+2
  1343.         jne    FragNextBuf
  1344.         cmp    si,[di].iIpId
  1345.         jne    FragNextBuf
  1346.         cmp    ch,[di].iIpProt
  1347.         je    FragBufFound
  1348.   FragNextBuf:
  1349.         push    si            ; irrelevant buf, put it back
  1350.         mov    si,offset FragList
  1351.         call    AddToList
  1352.         pop    si
  1353.         dec    cl
  1354.         jnz    FragLook4Buf
  1355.   FragEarliest:
  1356.         call    FragFirstLast        ; compute addr of fragment
  1357.         or    ax,ax            ; first part earliest?
  1358.         jnz    FragOffset
  1359.  
  1360.         mov    bx,bp        
  1361.         mov    di,[bx].dPtrUdp
  1362.         add    di,dx
  1363.         cmp    [bp].dHomeList,offset FreeBufs ;   and a big buffer?
  1364.         je    FragFirstHole        ; - yes, no extra buffer needed
  1365.   FragOffset:
  1366.         call    BufAlloc        ; - no, create empty buffer
  1367.         jz    VerifyFragErr
  1368.  
  1369.         add    di,2+2*EADDR_LEN
  1370.         mov    [bx].dPtrIp,di
  1371.  
  1372.         mov    si,[bp].dPtrIP
  1373.         mov    cx,[bp].dPtrUdp        ; copy IP header
  1374.         sub    cx,si
  1375.         call    movemem
  1376.         mov    [bx].dPtrUdp,di
  1377.   FragFirstHole:
  1378.         mov    [di].holeNext,0     ; create first hole descriptor
  1379.         mov    [di].holeFirst,0
  1380.         mov    [di].holeLast,GIANT
  1381.         mov    [bx].dPtrFrag,di
  1382.  
  1383.         add    di,HOLEDESCRLEN     ; mark end of info
  1384.         mov    [bx].dPktEnd,di
  1385.   FragBufFound:
  1386.         call    FragFirstLast        ; compute addr of fragment
  1387.         lea    di,[bx].dPtrFrag
  1388.   FragNextHole:                 ; 1. select next hole descr
  1389.         mov    si,di
  1390.         mov    di,[si].holeNext
  1391.         or    di,di            ;    any more descriptors?
  1392.         jz    FragEndHoles
  1393.  
  1394.         cmp    ax,[di].holeLast    ; 2. frag.first > hole.last?
  1395.         jae    FragNextHole
  1396.  
  1397.         cmp    dx,[di].holeFirst    ; 3. frag.last < hole.first?
  1398.         jbe    FragNextHole
  1399.  
  1400.         mov    cx,[di].holeNext    ; 4. delete current hole descr
  1401.         mov    [si].holeNext,cx
  1402.  
  1403.         mov    cx,[di].holeLast
  1404.         cmp    ax,[di].holeFirst    ; 5. frag.first > hole.first?
  1405.         jbe    FragNoNew1
  1406.         mov    [si].holeNext,di    ;    create new hole descr
  1407.         mov    [di].holeLast,ax
  1408.   FragNoNew1:
  1409.         mov    si,[bp].dPtrIp        ; 6. if frag.more
  1410.         test    [si].iIpFlFrag,0020h
  1411.         jz    FragLastFrag
  1412.  
  1413.         cmp    dx,cx            ;    and frag.last < hole.last?
  1414.         jae    FragNextHole
  1415.  
  1416.         mov    si,[bx].dPtrUdp
  1417.         add    si,dx
  1418.         mov    [si].holeFirst,dx    ;    create new hole descr
  1419.         mov    [si].holeLast,cx
  1420.         mov    cx,[bx].dPtrFrag
  1421.         mov    [si].holeNext,cx
  1422.         mov    [bx].dPtrFrag,si
  1423.  
  1424.         add    si,HOLEDESCRLEN
  1425.         cmp    si,[bx].dPktEnd
  1426.         jbe    FragNextHole
  1427.   FragPktEnd:
  1428.         mov    [bx].dPktEnd,si
  1429.         jmp    short FragNextHole
  1430.  
  1431.   FragLastFrag:                 ; when last frag
  1432.         mov    si,[bx].dPtrUdp     ;   prepare IP length
  1433.         add    si,dx
  1434.         jmp    short FragPktEnd
  1435.  
  1436.   FragEndHoles:                 ; 8. copy data to assembly buf
  1437.         cmp    bx,bp            ; do we need to copy?
  1438.         je    FragTimeUpd
  1439.  
  1440.         or    ax,ax            ; if first frag
  1441.         jnz    FragNotFirst
  1442.  
  1443.         mov    si,[bx].dPtrUdp     ;   retain this IP header
  1444.         mov    di,[bp].dPtrUdp     ;   and copy assembled data
  1445.         mov    cx,[bx].dPktEnd     ;   to frag buffer
  1446.         sub    cx,si
  1447.         add    si,dx            ;   skip over first fragment
  1448.         add    di,dx
  1449.         sub    cx,dx
  1450.         call    movemem
  1451.         mov    [bp].dPktEnd,di
  1452.  
  1453.         mov    cx,[bx].dPtrFrag
  1454.         mov    [bp].dPtrFrag,cx
  1455.  
  1456.         xchg    bx,bp            ;   and switch buffers
  1457.  
  1458.         mov    cx,di
  1459.         sub    cx,si            ;   hole ptr adjustment
  1460.         lea    di,[bx].dPtrFrag
  1461.   FragUpdLoop:
  1462.         mov    si,di
  1463.         mov    di,[si].holeNext
  1464.         or    di,di
  1465.         jz    FragRelBuf        ;   end of hole list 
  1466.  
  1467.         add    di,cx
  1468.         mov    [si].holeNext,di    ;   new pointer address
  1469.         jmp    short FragUpdLoop
  1470.  
  1471.   FragNotFirst:
  1472.         mov    si,[bp].dPtrUdp     ; copy this frag to asm buf
  1473.         mov    cx,dx
  1474.         sub    cx,ax
  1475.         mov    di,[bx].dPtrUdp
  1476.         add    di,ax
  1477.         call    movemem
  1478.   FragRelBuf:
  1479.         push    bx            ; release frag buf
  1480.         mov    bx,bp
  1481.         call    BufRelease
  1482.         pop    bx
  1483.   FragTimeUpd:
  1484.         call    CurrentTicks        ; update timer entry
  1485.         mov    di,[bx].dPtrIp
  1486.         mov    al,[di].iIpTtl
  1487.         mul    k18
  1488.         add    cx,ax
  1489.         mov    [bx].dTickTimeout,cx
  1490.  
  1491.         mov    di,[bx].dPtrIp
  1492.         mov    si,[bx].dPtrUdp
  1493.         cmp    [bx].dPtrFrag,0     ; any holes?
  1494.         jne    FragKeep        ; - yes, wait for more pkts
  1495.  
  1496.         mov    cx,[bx].dPktEnd     ; - no
  1497.         mov    ax,cx            ; compute IP length
  1498.         sub    cx,[bx].dPtrIp
  1499.         xchg    ch,cl
  1500.         mov    [di].iIpLen,cx
  1501.  
  1502.         add    sp,4            ; pop si and pop di
  1503.         ret
  1504.  
  1505.   FragKeep:
  1506.         mov    si,offset FragList    ; keep buf a while
  1507.         call    AddToList
  1508.         jmp    VerifyKeep
  1509. VerifyIpHdr    endp
  1510.  
  1511.  
  1512.  
  1513. ;************************************************************************
  1514. ;*        FragFirstLast
  1515. ;************************************************************************
  1516.  
  1517. FragFirstLast    proc    near
  1518.         mov    di,[bp].dPtrIp        ; compute frag.first
  1519.         mov    ax,[di].iIpFlFrag
  1520.         xchg    ah,al
  1521.         and    ax,1fffh
  1522.         shl    ax,1
  1523.         shl    ax,1
  1524.         shl    ax,1
  1525.         mov    dx,[di].iIpLen        ; compute frag.last (+1)
  1526.         xchg    dh,dl
  1527.         add    dx,[bp].dPtrIp
  1528.         sub    dx,[bp].dPtrUdp
  1529.         add    dx,ax
  1530.         cmp    dx,GIANT-IPHDRLEN-HWHDRLEN ; fits in buffer?
  1531.         ja    FragTooBig
  1532.  
  1533.         ret
  1534.  
  1535.   FragTooBig:
  1536.         add    sp,2            ; remove return addr from stack
  1537.         jmp    FragAddAndErr
  1538. FragFirstLast    endp
  1539.  
  1540.  
  1541.  
  1542. ;************************************************************************
  1543. ;*        AgeFrags
  1544. ;************************************************************************
  1545.  
  1546. AgeFragsNext    dw    0
  1547.  
  1548. AgeFrags    proc    near
  1549.         call    CurrentTicks
  1550.         cmp    cx,AgeFragsNext
  1551.         jns    AgeFragsNow        ; time to age yet?
  1552.  
  1553.         ret
  1554.  
  1555.   AgeFragsNow:
  1556.         mov    dx,cx
  1557.         add    cx,2*18         ; check next in 2 seconds
  1558.         mov    AgeFragsNext,cx
  1559.  
  1560.         push    bx
  1561.         PushfDI
  1562.         mov    cx,Fraglist.lBufsAvail
  1563.   AgeLook4Buf:
  1564.         mov    di,offset FragList
  1565.         call    GetFromList
  1566.         jz    AgeNoMoreFrags        ; any reassembly buffers?
  1567.  
  1568.         mov    si,offset FragList
  1569.         cmp    dx,[bx].dTickTimeout
  1570.         js    AgenextBuf        ; too old?
  1571.                         ; - no, put it back
  1572.         mov    si,[bx].dHomeList    ; - yes, release it
  1573.   AgeNextBuf:
  1574.         call    AddToList            
  1575.  
  1576.         dec    cl
  1577.         jnz    AgeLook4Buf        ; any more reassembly bufs?
  1578.   AgeNoMoreFrags:
  1579.         PopfEI
  1580.         pop    bx
  1581.         ret
  1582. AgeFrags    endp
  1583.  
  1584. endif ; RFCC
  1585.  
  1586. ;************************************************************************
  1587. ;*        SwitchIpDst
  1588. ;************************************************************************
  1589.  
  1590. SwitchIpDst    proc    near
  1591.         mov    si,[bx].dPtrIp
  1592. SwitchIpDstB:
  1593.         mov    dx,[si].iIpSrc        ; mov his IP # to IP dst
  1594.         mov    di,[bx].dPtrIp
  1595.         mov    [di].iIpDst,dx
  1596.         mov    dx,[si].iIpSrc+2
  1597.         mov    [di].iIpDst+2,dx
  1598.         ret
  1599. SwitchIpDst    endp
  1600.  
  1601.  
  1602.  
  1603. ;************************************************************************
  1604. ;*        InitIp
  1605. ;************************************************************************
  1606.  
  1607. InitIp        proc    near
  1608.  
  1609.         push    sp
  1610.         pop    ax
  1611.         cmp    ax,sp            ; 286 or better?
  1612.         jne    IsNot386
  1613.  
  1614.         pushf
  1615.         pop    ax
  1616.         or    ax,7000h        ;the 386 lets us set these bits
  1617.         push    ax
  1618.         popf
  1619.         pushf
  1620.         pop    ax
  1621.         test    ax,7000h        ;did the bits get set?
  1622.         jz    IsNot386        ;no.
  1623.         or    GenFlags,IS_386        ;yes, use a 386-optimized code
  1624.   IsNot386:
  1625.         push    ds
  1626.         mov    IpDesBuf.dPtrPhys,offset IpDesBuf.fHwStruc ; *test*
  1627.         mov    IpDesBuf.dPtrIp,offset IpDesBuf.fIpStruc
  1628.         mov    IpDesBuf.dPtrUdp,offset IpDesBuf.fBotStruc
  1629.  
  1630.         mov    ax,1ffh         ;driver_info
  1631.         int_pkt
  1632.         pop    ds
  1633.         call    fatal_error
  1634.  
  1635.         mov    ah,2            ;access all packets.
  1636.         mov    al,ch            ;their class from driver_info().
  1637.         mov    bx,dx            ;their type from driver_info().
  1638.         mov    dl,cl            ;their number from driver_info().
  1639.         mov    cx,2            ;type length of two.
  1640.         mov    si,offset IpDesBuf.fHwStruc.hProtType
  1641.         push    cs            ;es:di -> our receiver.
  1642.         pop    es
  1643.         mov    di,offset IpRecv
  1644.  
  1645.         push    ds
  1646.         int_pkt
  1647.         pop    ds
  1648.  
  1649.         call    fatal_error
  1650.  
  1651.         mov    IpHandle,ax
  1652.  
  1653.         ret
  1654. InitIp        endp
  1655.  
  1656.  
  1657.  
  1658. ;************************************************************************
  1659. ;*        EndProtocol
  1660. ;************************************************************************
  1661.  
  1662. EndProtocol    proc    near
  1663.         mov    ah,3            ; release handle in bx
  1664.  
  1665.         push    ds
  1666.         int_pkt
  1667.         pop    ds
  1668.  
  1669.         call    print_error
  1670.  
  1671.         ret
  1672. EndProtocol    endp
  1673.  
  1674.  
  1675.  
  1676. ;************************************************************************
  1677. ;*        Terminate
  1678. ;************************************************************************
  1679.  
  1680. Terminate    proc    near
  1681.         pop    bx            ; remove return addr fr stack
  1682.         push    ax
  1683.  
  1684.         cld
  1685.         push    cs
  1686.         push    cs
  1687.         pop    ds
  1688.         pop    es
  1689.         sti
  1690.  
  1691.         mov    bx,IpHandle        ; release ARP and IP handles
  1692.         call    EndProtocol
  1693.         mov    bx,ArpHandle
  1694.         call    EndProtocol
  1695. if PINGCLIENT
  1696.         cmp    EchoTarget,0
  1697.         jz    TermNoPing
  1698.         call    RestoreTimer
  1699.   TermNoPing:
  1700. endif ; PINGCLIENT
  1701.         pop    ax
  1702.         push    ax
  1703.         or    al,al            ; any errors?
  1704.         jz    termnorm
  1705.  
  1706.         cmp    EnoughWord,HAVE_MYIPNR    ; clock errors?
  1707.         je    termnorm
  1708.  
  1709.         mov    dx,offset MsgNotSet    ; display "clock not set"
  1710.         mov    ah,9
  1711.         int    21h
  1712.   termnorm:
  1713.         pop    ax
  1714.         push    ax
  1715.         add    al,'0'
  1716.         mov    MsgTermNr,al        ; show error # in end line
  1717.  
  1718.         mov    si,offset MyHwAd
  1719.         mov    di,offset MsgTermHw
  1720.         call    PutHwNum        ; put my HW addr
  1721.  
  1722.         mov    si,offset MyIpNr
  1723.         mov    di,offset MsgMyIp
  1724.         call    PutIpNum        ; put my IP #
  1725.  
  1726.         mov    dx,offset MsgTerm    ; End of PDCLKSET msg
  1727.         mov    ah,9
  1728.         int    21h
  1729.  
  1730.         pop    ax            ; error code
  1731.         mov    ah,4ch
  1732.         int    21h            ; terminate program
  1733. Terminate    endp
  1734.  
  1735.  
  1736.  
  1737.  
  1738. ;************************************************************************
  1739. ;*        IP receiver                        *
  1740. ;************************************************************************
  1741.  
  1742. IpRecv:
  1743.         pushf
  1744.         push    ds            ; set segment registers
  1745.         mov    dx,cs
  1746.         mov    ds,dx
  1747.         mov    es,dx
  1748.         cld
  1749.  
  1750.         or    ax,ax            ; first or second call?
  1751.         jne    IpRecv_1        ; - second, we've got data
  1752.                         ; - first, they want a buf
  1753.         cmp    cx,GIANT        ; packet too long?
  1754.         ja    IpRecTooBig
  1755. if PINGCLIENT
  1756.         cmp    cx,BUFBODYSML
  1757.         ja    IpRecBig
  1758.  
  1759.         call    BufAlSml
  1760.         jz    IpRecBig
  1761.         pop    ds
  1762.         popf
  1763.         retf
  1764.  
  1765.   IpRecBig:
  1766. endif ; PINGCLIENT
  1767.         call    BufAlloc        ; get a receive buffer
  1768.         jz    IpRecNoBuf
  1769.   IpRecRet0:
  1770.         pop    ds
  1771.         popf
  1772.         retf
  1773.  
  1774. if DEBUG
  1775.   DbgIpRecv:
  1776.         or    GenFlags,DBGINTERR
  1777. endif ; DEBUG
  1778.   IpRecNoBuf:
  1779. if PINGCLIENT
  1780.         inc    EchoDrop
  1781. endif ; PINGCLIENT
  1782.   IpRecTooBig:
  1783.         xor    di,di            ; no buffer available
  1784.         mov    es,di
  1785.         jmp    short IpRecRet0
  1786.  
  1787.  
  1788.   IpRecv_1:
  1789.  
  1790. ; If I understand PC interrupt handling correctly, the following stackswitch
  1791. ; and interrupt enabling should not kill multiprocess reentrancy.
  1792.  
  1793.         cli                ; switch to our
  1794.         mov    word ptr SaveSP,sp    ;   interrupt stack
  1795.         mov    word ptr SaveSS,ss
  1796.         mov    sp,offset StackEnd
  1797.         mov    ss,MySegm
  1798.         sti                ; allow interrupts
  1799. if DEBUG
  1800.         dec    DbgIntCnt        ; double interrupt?
  1801.         jnz    DbgIpRecv
  1802. endif ; DEBUG
  1803.         call    BuildRecDescr        ; calculate pointers etc
  1804.  
  1805.         call    IpChkSum        ; only accept a correct
  1806.         jne    IpRecRet        ;   IP checksum
  1807.  
  1808.         mov    [bx].dPtrUdp,si
  1809. if RFCC
  1810.         call    VerifyIpHdr        ; verify and process IP hdr
  1811.         jc    IpRecKeepBuf
  1812. endif ; RFCC
  1813.         mov    cx,[di].iIpLen        ; calculate IP data length
  1814.         xchg    ch,cl
  1815.         add    cx,di
  1816.         sub    cx,si
  1817.         mov    [bx].dPktLen,cx     ; save IP data length
  1818. if PINGCLIENT
  1819.         mov    ax,cx
  1820.         add    ax,IPHDRLEN+14+8+4+12    ; preamble, crc, intergap
  1821.         add    EchoLoad+2,ax
  1822.         adc    EchoLoad,0
  1823. endif ; PINGCLIENT
  1824.         cmp    [di].iIpProt,ICMP_PROT    ; ICMP protocol?
  1825.         jne    IpNotIcmp
  1826.         jmp    IpRecIcmp
  1827.   IpNotIcmp:
  1828.         cmp    [di].iIpProt,UDP_PROT    ; UDP protocol?
  1829.         jne    IpProtUnr
  1830.  
  1831.         call    UdpChkSum        ; if available, test 
  1832.         jne    IpRecRet        ;   UDP checksum
  1833.  
  1834.         cmp    si,[bx].dPktEnd     ; still within packet limit?
  1835.         jbe    IpRecUdp
  1836.   IpRecRet:
  1837.         call    BufRelease        ; release receive buffer
  1838.   IPRecKeepBuf:
  1839. if DEBUG
  1840.         inc    DbgIntCnt
  1841. endif ; DEBUG
  1842.         cli                ; restore previous stack
  1843.         mov    sp, word ptr SaveSP
  1844.         mov    ss, word ptr SaveSS
  1845.         pop    ds
  1846.         popf
  1847.         retf
  1848.  
  1849.  
  1850.   IpProtUnr:
  1851.         mov    ah,2            ; protocol unreachable
  1852.         jmp    short IpUnr
  1853.   IpPortUnr:
  1854.         mov    ah,3            ; port unreachable
  1855.   IpUnr:
  1856. if RFCC
  1857.         mov    al,3            ; destination unreachable
  1858.  
  1859.         cmp    [bx].dIdxHwDst,ARPMYIDX ; was it specifically to me?
  1860.         jne    IpRecRet
  1861.  
  1862.         mov    bp,bx
  1863.         call    BufAlloc
  1864.         jz    UnrEnd
  1865.         call    MakeSendDescr
  1866.         mov    si,[bp].dPtrIp        ; copy IP header
  1867.         mov    cx,[bp].dPtrUdp
  1868.         add    cx,8            ;   + 8 bytes
  1869.         sub    cx,si
  1870.  
  1871.         call    SwitchIpDstB        ; return to sender
  1872.  
  1873.         mov    di,[bx].dPtrUdp
  1874.         mov    [di].uIcmpTypecode,ax    ; set type and code
  1875.  
  1876.         add    di,8
  1877.         call    movemem
  1878.  
  1879.         sub    di,[bx].dPtrUdp
  1880.         mov    [bx].dPktLen,di     ; set IP data length
  1881.  
  1882.         mov    si,offset IcmpToDo    ; put buf on the ICMP send list
  1883.         call    AddToList
  1884.   UnrEnd:
  1885.         mov    bx,bp
  1886. endif ; RFCC
  1887.         jmp    IpRecRet
  1888.  
  1889.  
  1890.   IpRecUdp:
  1891.         mov    [bx].dPktEnd,si         ; end of logical pkt
  1892.  
  1893.         mov    di,[bx].dPtrUdp
  1894.         cmp    word ptr [di].uUdpSrc,2500h    ; Src port 0025 = 37 ?
  1895.         je    IpRecvTime            ; - must be time reply
  1896. if TBLBUILD or PINGCLIENT
  1897.         cmp    word ptr [di].uUdpSrc,3500h    ; Name server (53)?
  1898.         jne    $+5
  1899.         jmp    IpRecvName
  1900.         cmp    word ptr [di].uUdpDst,0703h    ; Udp Echo?
  1901.         jne    $+5
  1902.         jmp    IpEchoReply
  1903.         cmp    word ptr [di].uUdpDst,0700h    ; Udp Echo request?
  1904.         jne    $+5
  1905.         jmp    IpEchoRequest
  1906.         cmp    word ptr [di].uUdpDst,0900h    ; Udp Discard request?
  1907.         jne    $+5
  1908.         jmp    IpDiscard
  1909. endif ; TBLBUILD or PINGCLIENT
  1910.         cmp    word ptr [di].uUdpSrc,4300h    ; Src port 0043 = 67
  1911.         jne    IpPortUnr
  1912.  
  1913.         cmp    word ptr [di].uUdpDst,4400h    ; Dst port 0044 = 68
  1914.         jne    IpPortUnr
  1915.  
  1916.         cmp    byte ptr [di].uBotOp,2    ; bootp reply?
  1917.         jne    IpRecRet2
  1918.   IpRecBootp:
  1919.         push    di            ; - must be bootp reply
  1920.         lea    si,[di].uBotCliHwAd
  1921.         mov    di,offset MyHwAd
  1922.         mov    cx,Hlen
  1923.         repe    cmpsb            ; our Ethernet addr?
  1924.         pop    di
  1925.         jne    IpRecRet2
  1926.  
  1927.         mov    ax,word ptr IpDesBuf.fBotStruc.uBotXid  
  1928.         cmp    ax,word ptr [di].uBotXid    ; our random id?
  1929.         jne    IpRecRet2
  1930.         mov    ax,word ptr IpDesBuf.fBotStruc.uBotXid+2
  1931.         cmp    ax,word ptr [di].uBotXid+2
  1932.         jne    IpRecRet2
  1933.                         ; yes, it's about me!
  1934.         mov    dx,[di].uBotGwyIp    ; saves an ARP request
  1935.         mov    ax,[di].uBotGwyIp+2    ;   in many cases
  1936.         mov    si,[bx].dPtrPhys
  1937.         add    si,Hlen
  1938.         call    ArpPutNew
  1939.  
  1940.         test    Events,GOT_BOOTP    ; if first answer
  1941.         jnz    IpRecRet2        ;   save bootp answer
  1942.  
  1943.         mov    AdrBootpReply,bx    ;   for further study 
  1944.         or    Events,GOT_BOOTP
  1945.         jmp    IpRecKeepBuf
  1946.  
  1947.   IpRecvTime:
  1948.         test    Events,GOT_TIMEREPLY    ; already got reply?
  1949.         jnz    IpRecRet2
  1950.  
  1951.         mov    ax,[di].uUdpData    ; save seconds
  1952.         mov    cTime,ax        ;   since year 1900
  1953.         mov    ax,[di].uUdpData+2
  1954.         mov    cTime+2,ax
  1955.  
  1956.         mov    di,[bx].dPtrIp        ; save who was answering
  1957.         mov    dx,[di].iIpSrc
  1958.         mov    ax,[di].iIpSrc+2
  1959.         mov    RespondingIpNr,dx
  1960.         mov    RespondingIpNr+2,ax
  1961.         or    Events,GOT_TIMEREPLY
  1962.   IpRecRet2:
  1963.         jmp    IpRecRet
  1964.  
  1965. if TBLBUILD or PINGCLIENT
  1966.   IpRecvName:
  1967.         mov    si,offset NameToDo    ; process nameserver reply
  1968.         call    AddToList
  1969.         jmp    IpRecKeepBuf
  1970. endif ; TBLBUILD or PINGCLIENT
  1971.  
  1972.  
  1973.   IpRecIcmp:
  1974.         call    SwitchIpDst        ; in case we want to return it
  1975.  
  1976.         call    IcmpChkSum        ; valid ICMP checksum?
  1977.         jne    IpRecRet2
  1978.  
  1979.         mov    si,[bx].dPtrUdp     ; point to ICMP header
  1980.         mov    cx,[si].uIcmpTypecode    ; get type and code
  1981.         mov    dx,[si].uIcmpIpHdr.iIpDst    ; get original IP hdr
  1982.         mov    ax,[si].uIcmpIpHdr.iIpDst+2    ;   dst IP #
  1983.  
  1984. if PINGCLIENT
  1985.         cmp    cl,0            ; echo reply?
  1986.         jne    IpNotEchoReply
  1987.   IpEchoReply:
  1988.         call    EchoCalc
  1989.         jmp    IpRecRet
  1990. endif ; PINGCLIENT
  1991.  
  1992. if RFCC
  1993.   IpNotEchoReply:
  1994.         cmp    cl,8            ; echo request?
  1995.         jne    IpNotEchoReq
  1996.  
  1997.         mov    byte ptr [si].uIcmpTypecode,0 ; put echo reply value
  1998.   IpQueReply:
  1999.         cmp    [bx].dIdxHwDst,ARPMYIDX ; broadcast?
  2000.         jb    IpRecRet2        ; - yes, don't echo
  2001.  
  2002.         mov    si,offset IcmpToDo    ; put buf on the ICMP send list
  2003.         call    AddToList
  2004.         jmp    IpRecKeepBuf
  2005.  
  2006.   IpNotEchoReq:
  2007. endif ; RFCC
  2008.  
  2009.         cmp    cx,11            ; TTL exceeded?
  2010.         je    IpIcmpUnreach
  2011.  
  2012.         cmp    cl,3            ; unreachable
  2013.         jne    IpNotUnreach
  2014.  
  2015.         cmp    ch,12            ; net or host unreachable?
  2016.         ja    IpIcmpRet2
  2017.         cmp    ch,6
  2018.         ja    IpIcmpUnreach
  2019.         cmp    ch,1
  2020.         ja    IpIcmpRet2
  2021.   IpIcmpUnreach:                ; codes 0 - 1, 6 - 12 go here
  2022.         PushfDI
  2023.         push    si
  2024.         mov    cl,[si].uIcmpIpHdr.iIpTos
  2025.         xor    ch,ch
  2026.         mov    si,cx
  2027.         call    RouteFind        ; this host in route table?
  2028.         pop    si
  2029.         jnz    IpIcmpUnfound
  2030.  
  2031.         mov    ah,byte ptr [si].uIcmpTypeCode+1 ; icmp code
  2032.         xor    al,al        ;*test
  2033.         inc    ah            ; ensure non zero error code
  2034.         mov    RouteTabUnreach[di],ax    ; mark it unreachable
  2035.  
  2036.         call    CurrentTicks        ; get current ticks value
  2037.         mov    RouteTabTrRx[di],cx    ; set timer
  2038.   IpIcmpUnfound:
  2039.         PopfEI
  2040.   IpIcmpRet2:
  2041.         jmp    IpIcmpRet
  2042.  
  2043.   IpNotUnreach:
  2044. if RFCC
  2045.         cmp    cl,4            ; source quench
  2046.         jne    IpIcmpNotQuench
  2047.  
  2048.         PushfDI
  2049.         push    si
  2050.         mov    cl,[si].uIcmpIpHdr.iIpTos
  2051.         xor    ch,ch
  2052.         mov    si,cx
  2053.         call    RouteFind        ; this host in route table?
  2054.         pop    si
  2055.         jnz    IpIcmpNotRoute
  2056.  
  2057.         mov    dx,RouteTabFlags[di]
  2058.         or    RouteTabFlags[di],SQ_UPDATED
  2059.         lea    si,RouteTabTrSq[di]
  2060.         lea    di,RouteTabSqDelay[di]
  2061.         jmp    short IpIcmpSq
  2062.   IpIcmpNotRoute:
  2063.         call    ArpFindIp
  2064.         jnz    IpIcmpSqEnd
  2065.  
  2066.         mov    dx,ArpTabFlags[di]
  2067.         or    ArpTabFlags[di],SQ_UPDATED
  2068.         lea    si,ArpTabTrSq[di]
  2069.         lea    di,ArpTabSqDelay[di]
  2070.   IpIcmpSq:
  2071.         mov    ax,[di]         ; get current sq delay
  2072.         or    ax,ax
  2073.         jnz    IpIcmpAddDelay
  2074.         call    CurrentTicks
  2075.         mov    [si],cx         ; initialize sq timer
  2076.         mov    ax,150*64/55        ; initial sq delay 178 ms
  2077.   IpIcmpAddDelay:
  2078.         add    ax,28*64/55        ; increase delay by 28 ms
  2079.         test    dx,SQ_UPDATED        ;   unless already done in
  2080.         jnz    IpIcmpSqEnd        ;   the last two seconds
  2081.         mov    [di],ax
  2082.   IpIcmpSqEnd:
  2083.         PopfEI
  2084.         jmp    short IpIcmpRet
  2085.  
  2086.   IpIcmpNotQuench:
  2087. endif ; RFCC
  2088.         cmp    cl,5            ; redirect
  2089.         jne    IpNotRedirect
  2090.  
  2091.         PushfDI
  2092.         push    si
  2093.         mov    cl,[si].uIcmpIpHdr.iIpTos
  2094.         xor    ch,ch
  2095.         mov    si,cx
  2096.         call    RouteFind        ; this host in route table?
  2097.         pop    si
  2098.         jnz    IpIcmpDisfound
  2099.  
  2100.         mov    dx,RouteTabIpG1[di]    ; icmp from the gwy used?
  2101.         mov    ax,RouteTabIpG2[di]
  2102.         mov    cx,di
  2103.         mov    di,[bx].dPtrIp
  2104.         cmp    dx,[di].iIpSrc
  2105.         jne    IpIcmpDisfound
  2106.         cmp    ax,[di].iIpSrc+2
  2107.         jne    IpIcmpDisfound
  2108.         mov    di,cx
  2109.  
  2110.         mov    dx,[si].uIcmpData    ; new gateway IP #
  2111.         mov    ax,[si].uIcmpData+2
  2112.  
  2113.         call    MyNetChk        ; is he on my net?
  2114.         jnz    IpIcmpDisfound
  2115.  
  2116.         mov    RouteTabIpG1[di],dx    ; put it into route table
  2117.         mov    RouteTabIpG2[di],ax
  2118.   IpIcmpDisfound:
  2119.         PopfEI
  2120.         jmp    short IpIcmpRet
  2121.  
  2122.   IpNotRedirect:
  2123.   IpIcmpRet:
  2124.         jmp    IpRecRet
  2125.  
  2126. if RFCC
  2127.   IpEchoRequest:
  2128.         call    SwitchIpDst
  2129.  
  2130.         mov    si,[bx].dPtrUdp
  2131.  
  2132.         mov    dx,[si].uUdpDst        ; swap udp src and dst ports
  2133.         mov    ax,[si].uUdpSrc
  2134.         mov    [si].uUdpDst,ax
  2135.         mov    [si].uUdpSrc,dx
  2136.         add    EchoRx32+2,1        ; increment receive counters
  2137.         adc    EchoRx32,0
  2138.         add    EchoTx32+2,1        ; increment tramsmit counters
  2139.         adc    EchoTx32,0
  2140.         jmp    IpQueReply
  2141.  
  2142.   IpDiscard:
  2143.         add    EchoRx32+2,1        ; increment receive counters
  2144.         adc    EchoRx32,0
  2145.         jmp    IpRecRet
  2146. endif ; RFCC
  2147.  
  2148.  
  2149. ;************************************************************************
  2150. ;*        MakeMynet
  2151. ;************************************************************************
  2152.  
  2153. MakeMynet    proc    near
  2154.         mov    dx,MyIpNr
  2155.         mov    ax,MyIpNr+2
  2156.  
  2157.         mov    ArpTabIp1+4,dx        ; third arp slot = me
  2158.         mov    ArpTabIp2+4,ax
  2159.         mov    si,offset MyHwAd
  2160.         call    ArpPutNew
  2161.  
  2162.         mov    si,MyMask
  2163.         mov    di,MyMask+2
  2164.         and    dx,si            ; calculate network #
  2165.         and    ax,di
  2166.         mov    MyNet,dx
  2167.         mov    MyNet+2,ax
  2168.  
  2169.         not    si            ; second arp slot =
  2170.         not    di            ;   subnet broadcast
  2171.         or    dx,si
  2172.         or    ax,di
  2173.         mov    ArpTabIp1+2,dx
  2174.         mov    ArpTabIp2+2,ax
  2175.         ret
  2176. MakeMynet    endp
  2177.  
  2178.  
  2179.  
  2180. ;************************************************************************
  2181. ;*        ValidateIpNr
  2182. ;************************************************************************
  2183.  
  2184. ValidateIpNr    proc    near
  2185.         call    BufAlloc
  2186.  
  2187.         mov    [bx].dTimOutMsg,0    ; we SHOULD get no answer
  2188.         mov    [bx].dTickTimeout,10    ; give them half a second
  2189.         mov    dx,MyIpNr
  2190.         mov    ax,MyIpNr+2
  2191.         call    SendArpReq        ; send arp to our Ip #
  2192.         call    BufRelease
  2193.         jz    ValConflict        ; someone else has our IP # ?
  2194.  
  2195.         ret                ; - no, return
  2196.  
  2197.   ValConflict:                    ; - yes, error termination
  2198.         call    ArpFindIp
  2199.         mov    cl,3
  2200.         shl    di,cl
  2201.         lea    si,ArpTabHwAdr[di]    ; get HW addr of arp reply
  2202.  
  2203.         mov    di,offset OccupiedHw
  2204.         call    PutHwNum        ; put offending HW addr
  2205.  
  2206.         mov    dx,offset OccupiedMsg    ; display IP occupied msg
  2207.         mov    ah,9
  2208.         int    21h
  2209.  
  2210.         mov    al,09            ; error code 9
  2211.         call    terminate
  2212. ValidateIpNr    endp
  2213.  
  2214.  
  2215.  
  2216. ;************************************************************************
  2217. ;*        DoBootpPkt
  2218. ;************************************************************************
  2219.  
  2220. DoBootpPkt    proc    near
  2221.         call    CurrentTicks        ; get current ticks value
  2222.         mov    IpDesBuf.fBotStruc.uBotXid,cx    ;   as transaction id
  2223. if RFCC
  2224.         add    cx,2*18         ; initialize ageing
  2225.         mov    AgeNext,cx
  2226.         mov    AgeFragsNext,cx
  2227. endif ; RFCC
  2228.         mov    al,byte ptr ArpBuf.iArpHtype+1
  2229.         mov    IpDesBuf.fBotStruc.uBotHtype,al ; put my HW type
  2230.  
  2231.         mov    si,offset MyHwAd
  2232.         mov    di,offset IpDesBuf.fBotStruc.uBotCliHwAd
  2233.         push    cs
  2234.         pop    es
  2235.         mov    cx,Hlen
  2236.         mov    IpDesBuf.fBotStruc.uBotHlen,cl
  2237.         rep    movsb                ; copy my HW addr
  2238.  
  2239.         mov    bx,offset IpDesBuf        ; frame to send
  2240.         call    MakeSendDescr
  2241.         mov    [bx].dWaitEvent,GOT_BOOTP    ; event to wait for
  2242.         mov    [bx].dTimOutMsg,offset NoBotReplyMsg ; error msg
  2243.         mov    ax,BpDataLen+UDPHDRLEN        ; bootp pkt length
  2244.         call    SendUdpPkt            ; send bootp request
  2245.  
  2246.         ret
  2247. DoBootpPkt    endp
  2248.  
  2249.  
  2250.  
  2251. ;************************************************************************
  2252. ;*        InterpBootp according to RFC 1084 and RFC1048
  2253. ;************************************************************************
  2254.  
  2255. InterpBootp    proc    near
  2256.         mov    bx,AdrBootpReply
  2257.         mov    di,[bx].dPtrUdp
  2258.         mov    dx,[di].uBotYourIp    ; mov my IP #
  2259.         mov    MyIpNr,dx        ;   to IP buf
  2260.         mov    ax,[di].uBotYourIp+2
  2261.         mov    MyIpNr+2,ax
  2262.  
  2263.         or    Flagword,HAVE_MYIPNR    ; note what we've got
  2264.  
  2265.         cmp    word ptr [di].uBotMagNum,8263h    ; RFC 1084 type of
  2266.         jne    VendEnd             ;   vendor area?
  2267.         cmp    word ptr [di].uBotMagNum+2,6353h
  2268.         jne    VendEnd
  2269.  
  2270.         lea    si,[di].uBotVend    ; start of "vendor area"
  2271.         lea    bp,[si]+64-4        ; end of "vendor area"
  2272.         push    cs
  2273.         pop    es
  2274.   VendLoop:
  2275.         cmp    si,bp            ; beyond vendor area?
  2276.         jb    VendNext
  2277.  
  2278.   VendEnd:
  2279.         call    BufRelease        ; release bootp reply buf
  2280.         ret
  2281.  
  2282.   VendNext:
  2283.         lodsb                ; get field type:
  2284.  
  2285.         cmp    al,0            ; filler
  2286.         je    VendLoop
  2287.  
  2288.         cmp    al,1            ; netmask
  2289.         jne    NotMask
  2290.         mov    di,offset MyMask
  2291.         call    Xtract4Bytes
  2292.         jmp    short VendLoop
  2293.   NotMask:
  2294.         cmp    al,2            ; zone/time (?) offset
  2295.         jne    NotTimeOffs
  2296.         test    Flagword,HAVE_TIMEOFFSET
  2297.         jnz    VendDefault
  2298.         mov    di,offset tzoffset
  2299.         call    Xtract4Bytes
  2300.         or    Flagword,HAVE_TIMEOFFSET
  2301.         jmp    short VendLoop
  2302.   NotTimeOffs:
  2303.         cmp    al,3            ; default gateways
  2304.         jne    NotDefGwys
  2305.         mov    di,offset DefGwys
  2306.         mov    cx,MAXDEFGWYS
  2307.         mov    ax,DefGwyNum
  2308.         call    XtractIpNums
  2309.         add    DefGwyNum,cx
  2310.         jmp    short VendLoop
  2311.   NotDefGwys:
  2312.         cmp    al,4            ; time servers
  2313.         jne    NotTimeserv
  2314.         or    Flagword,HAVE_TIMESERVER
  2315.         mov    di,offset TimeServIpNr
  2316.         mov    cx,MAXTSERVS
  2317.         mov    ax,TservNum
  2318.         call    XtractIpNums
  2319.         add    TservNum,cx
  2320.         jmp    short VendLoop
  2321.   NotTimeserv:
  2322. if TBLBUILD or PINGCLIENT
  2323.         cmp    al,6            ; default nameservers
  2324.         jne    NotDefNS
  2325.         mov    di,offset DefNS
  2326.         mov    cx,MAXDEFNS
  2327.         mov    ax,DefNSnum
  2328.         call    XtractIpNums
  2329.         add    DefNSnum,cx
  2330.         jmp    short VendLoop
  2331.   NotDefNS:
  2332. endif ; TBLBUILD or PINGCLIENT
  2333.         cmp    al,0ffh         ; end
  2334.         je    VendEnd
  2335.   VendDefault:                    ; everything else
  2336.         lodsb
  2337.         xor    ah,ah
  2338.         add    si,ax            ; skip field
  2339.         jmp    Vendloop
  2340.  
  2341. InterpBootp    endp
  2342.  
  2343.  
  2344.  
  2345. ;************************************************************************
  2346. ;*        XtractIpNums
  2347. ;************************************************************************
  2348.  
  2349. XtractIpNums    proc    near
  2350.         sub    cx,ax            ; wanted - already got
  2351.  
  2352.         shl    ax,1
  2353.         shl    ax,1
  2354.         add    di,ax            ; append to what we got
  2355.         shl    cx,1
  2356.         shl    cx,1
  2357.         jmp    short XtractNBytes
  2358. Xtract4Bytes:
  2359.         mov    cl,4
  2360. XtractNBytes:
  2361.         lodsb
  2362.         cmp    cl,al            ; as many as we want?
  2363.         jbe    XtractOkLen
  2364.  
  2365.         mov    cl,al            ; - no, take what there is
  2366.   XtractOkLen:
  2367.         xor    ch,ch
  2368.         xor    ah,ah
  2369.         push    cx
  2370.         push    ax
  2371.         push    si
  2372.         rep    movsb            ; copy field
  2373.         pop    si
  2374.  
  2375.         pop    ax
  2376.         add    si,ax            ; advance field ptr
  2377.  
  2378.         pop    cx
  2379.         shr    cx,1
  2380.         shr    cx,1            ; cx = IP #'s read
  2381.  
  2382.         ret
  2383. XtractIpNums    endp
  2384.  
  2385. ;========================================================================
  2386. ;        endinclude
  2387.